package butines.game2.states;

import butines.common.math.Vector2D;
import butines.game2.command.Command;
import butines.game2.command.CommandType;
import butines.game2.entity.Sprite.Type;
import butines.game2.entity.Entity;
import butines.game2.entity.Unit;
import butines.game2.messaging.Message;
import butines.game2.sterring.Path;

public class UnitStates {

    public final static State<Unit> STAY = Stay.getInstance();
    public final static State<Unit> MOVE = Move.getInstance();
    
    public static class Global extends AbstractState<Unit> {
        

        private static final Global instance = new Global();
        
        public static State<Unit> getInstance() {
            return instance;
        }
        
        @Override
        public boolean onMessage(Message message) {
            
            if (message.getType() == CommandType.STAY) {
                Entity entity = message.getReceiver();
                if (entity.isUnit()) {
                    entity.asUnit().getStateMachine().changeState(UnitStates.Stay.getInstance());
                }
                return true;
            }
            
            if (message.getType() == CommandType.MOVE) {
                Unit unit = message.getReceiver().asUnit();
                Command command = message.getArgs(0);
                
                unit.setToGridX(command.getTargetX());
                unit.setToGridY(command.getTargetY());

                if (unit.searchPath()) {
                    unit.changeState(MOVE);
                }
                
                return true;
            }
            
            return false;
        }
        
    }
        
    public static class Stay extends AbstractState<Unit> {

        private static final Stay instance = new Stay();
        
        public static State<Unit> getInstance() {
            return instance;
        }
        
        @Override
        public void enter(Unit unit) {
            unit.getVelocity().set(0, 0);
        }
        
        @Override
        public void execute(Unit unit) {
            unit.animate(Type.STAY, false);
        }

    }
    
    public static class Move extends AbstractState<Unit> {

        private static final Move instance = new Move();
        
        public static State<Unit> getInstance() {
            return instance;
        }
        
        @Override
        public void enter(Unit unit) {
            
        }

        @Override
        public void leave(Unit unit) {
            unit.getSteering().setFollowPath(false);
            unit.getVelocity().set(0, 0);
        }
        
        @Override
        public void execute(Unit unit) {
            
            Path path = unit.getSteering().getPath();
            Vector2D vec = path.getCurrentWaypoint();
            
            // Mapa alterado, procura nova rota
            if (unit.getGame().isRebuildMapPassableGrid()) {
                unit.getSteering().setFollowPath(false);
                if (!unit.searchPath()) {
                    unit.changeState(STAY);
                }
                return;
            }
            
            if (unit.getSteering().isFollowPath()) {
                unit.animate(Type.MOVE, true);
                if (path.isFinished() && unit.isAtPosition(vec)) {
                    unit.changeState(STAY);
                }
            } else if (unit.rotateHeadingToFacePosition(vec)) {
                unit.getSteering().setFollowPath(true);
            } else {
                unit.animate(Type.STAY, false);
            }

        }

    }
    
}
